import SignRecord from '@/model/SignRecord';
import User from '@/model/User';
import { getTokenPayload } from '../common/utils';
import moment from 'moment';
import sendMail from '@/config/mailConfig';
import { v4 as uuid } from 'uuid';
import jwt from 'jsonwebtoken';
import { setValue, getValue } from '@/config/redisConfig';
import config from '@/config';
import bcrypt from 'bcrypt';

class SignRecordController {
  // 用户签到接口
  async userSign (ctx) {
    // 取用户id
    const userPayload = await getTokenPayload(ctx.header.authorization);

    // 查询用户上一次签到记录
    const record = await SignRecord.getById(userPayload.id);

    // 查询用户信息
    let user = await User.getUserInfoById(userPayload.id);
    user = user[0];
    let { count } = user;
    let favs = 0;

    // 响应的数据
    let result = null;

    // 新的签到记录
    let newRecord = null;

    // 判断签到逻辑
    if (record) {
      // 有历史签到数据
      // 判断用户上一次签到记录的Created时间是否与今天相同
      if (moment(record.createTime).format('YYYY-MM-DD') === moment().format('YYYY-MM-DD')) {
        // 用户重复签到
        ctx.body = {
          code: 500,
          msg: '用户已经签到',
          count,
          favs: user.favs,
          lastSign: record.createTime
        };
        return;
      } else {
        // 用户没有重复签到，判断是否连续签到
        if (moment(record.createTime).format('YYYY-MM-DD') === moment().subtract(1, 'days').format('YYYY-MM-DD')) {
          // 连续签到则按公示的规则进行积分累加
          count += 1;
          if (count < 5) {
            favs = 5;
          } else if (count >= 5 && count < 15) {
            favs = 10;
          } else if (count >= 15 && count < 30) {
            favs = 15;
          } else if (count >= 30 && count < 100) {
            favs = 20;
          } else if (count >= 100 && count < 365) {
            favs = 30;
          } else if (count >= 365) {
            favs = 50;
          }
          // 更新用户表数据
          await User.updateOne({
            _id: userPayload.id
          }, {
            $inc: {
              favs: favs,
              count: 1
            }
          });
          // 更新响应数据
          result = {
            count: count,
            favs: user.favs + favs
          };
        } else {
          // 用户签到没有连续，按小于五天的规则累加积分
          favs = 5;
          // 更新用户表数据
          await User.updateOne({
            _id: userPayload.id
          }, {
            $inc: { favs: 5 },
            $set: { count: 1 }
          });
          // 更新响应数据
          result = {
            count: 1,
            favs: user.favs + favs
          };
        }
        // 新建一条签到记录数据插入到数据表中
        newRecord = SignRecord({
          uid: userPayload.id,
          favs,
          lastSign: record.createTime
        });
        newRecord.save();
      }
    } else {
      // 无历史签到数据 =>第一次进行签到
      // 更新用户表数据
      await User.updateOne({
        _id: userPayload.id
      }, {
        $set: { count: 1 },
        $inc: { favs: 5 }
      });
      // 新建一条签到记录数据插入到数据表中
      newRecord = SignRecord({
        uid: userPayload.id,
        favs: 5,
        lastSign: moment().format('YYYY-MM-DD HH:mm:ss')
      });
      newRecord.save();

      result = {
        favs: user.favs + 5,
        count: 1
      };
    }
    ctx.body = {
      code: 200,
      msg: '签到成功',
      ...result,
      lastSign: newRecord.createTime
    };
  }

  // 用户基本信息修改接口
  async updateUserInfo (ctx) {
    const { body } = ctx.request;
    const userPayloadInfo = await getTokenPayload(ctx.header.authorization);
    let msg = null;

    // 判断用户是否修改了邮箱
    const user = await User.findOne({ _id: userPayloadInfo.id });
    if (body.email && body.email !== user.email) {
      // 判断用户的新邮箱是否已经有人注册
      const tempUser = await User.findOne({ email: body.email });
      if (tempUser && tempUser.password) {
        ctx.body = {
          code: 501,
          msg: '该邮箱已经被注册'
        };
        return;
      }

      // 用户修改了邮箱，则发送 reset 邮件
      const key = uuid();
      setValue(key, jwt.sign({ id: user._id }, config.JWT.secret, { expiresIn: config.JWT.mailExpried }));
      const mailConfig = {
        type: 'email',
        data: {
          key: key,
          email: body.email
        },
        user: user.username,
        email: user.email,
        expried: moment().add(30, 'm').format('YYYY-MM-DD HH:mm:ss'),
        code: ''
      };
      await sendMail(mailConfig);
      msg = '用户信息更新成功，你修改了邮件信息，请点击验证邮箱的链接确认修改邮件账号';
    }

    // 过滤掉body不可直接更改的用户信息，同时保留接口的通用性
    const delProperty = ['email', 'mobile', 'password'];
    delProperty.forEach(item => {
      delete body[item];
    });
    const result = await User.update({ _id: userPayloadInfo.id }, body);
    if (result.n === 1 && result.ok === 1) {
      let newUser = await User.getUserInfoById(userPayloadInfo.id);
      newUser = newUser[0];
      newUser.email = user.email;
      ctx.body = {
        code: 200,
        msg: msg !== null ? msg : '更新成功',
        data: newUser
      };
    } else {
      ctx.body = {
        code: 500,
        msg: '服务器出了点小问题，更新失败'
      };
    }
  }

  // 修改用户邮箱接口
  async updateUserEmail (ctx) {
    const body = ctx.query;
    if (body.key) {
      const token = await getValue(body.key);
      const userInfo = getTokenPayload('Bearer ' + token);

      await User.updateOne({
        _id: userInfo.id
      }, {
        email: body.email
      });

      ctx.body = {
        code: 200,
        msg: '更新邮箱成功'
      };
    }
  }

  // 修改用户密码接口
  async changeUserPassword (ctx) {
    const passwordData = ctx.request.body;
    const userPayloadInfo = await getTokenPayload(ctx.header.authorization);
    const user = await User.findOne({ _id: userPayloadInfo.id });
    if (await bcrypt.compare(passwordData.oldpwd, user.password)) {
      await User.updateOne({ _id: userPayloadInfo.id }, {
        password: await bcrypt.hash(passwordData.newpwd, 5)
      });
      ctx.body = {
        code: 200,
        msg: '更新密码成功'
      };
    } else {
      ctx.body = {
        code: 500,
        msg: '请检查当前密码'
      };
    }
  }
}

export default new SignRecordController();
